#ifndef __MYSTRING_HPP__
#define __MYSTRING_HPP__

#include <iostream>
#include <cstring>

namespace mystring {
using namespace std;

class MyString {
 public:
  // 无参构造
  MyString() {
    size_ = 0;
    capacity_ = 100;
    str_ = new char[capacity_]{'\0'};
  }

  // 有参构造
  MyString(const char* str) {
    if (nullptr  == str) {  // 对字符串为空的情况进行处理
      size_ = 0;
      capacity_ = 100;
      str_ = new char[capacity_]{'\0'};
    } else {
      size_ = strlen(str);  // 计算输入字符串的长度并申请内存 strlen函数只统计字符个数不统计'\0'
      capacity_ = 2 * size_ + 1;
      str_ = new char[capacity_]; 
      strcpy(str_, str);     // 将输入字符串拷贝到str_中
    }
  }

  // 拷贝构造
  MyString(const MyString& that) {
    if (nullptr == &that) {  // 参数传递引用时一定要非空验证
      size_ = 0;
      capacity_ = 100;
      str_ = new char[capacity_]{'\0'};
    } else {
      size_ = that.size_;
      capacity_ = that.capacity_;
      str_ = new char[capacity_]{'\0'}; // 深度拷贝
      strcpy(str_, that.str_);
    }
  }

  // 析构
  ~MyString() {
    if (nullptr == str_) {
      delete[] str_;
      str_ = nullptr;
    }
  }

  // 计算字符串的字符个数
  int size(void) {
    return strlen(str_);
  }

  int size(const MyString& str) {
    return strlen(str.str_);
  }

   //清空字符串的字符
  void clear() {
    memset(str_, 0, capacity_);
    return;
  }

  void clear(MyString& str) {
    memset(str.str_, 0, str.capacity_);
  }

  //字符串赋值运算
  MyString& operator=(const MyString& other) {
    // 防止自赋值
    if (this != &other) {
      delete[] str_;  // 释放原有内存
      str_ = new char[strlen(other.str_) + 1];   // 深度赋值
      strcpy(str_, other.str_);
    }
    return *this;
  }

  MyString& operator=(const char* str) {
    MyString tmp_str(str);    // 调用普通构造，保存输入的字符串
    char* pstr = tmp_str.str_; // 交换字符串指针，使当前对象字符串指针指向输入的字符串
    tmp_str.str_ = str_;
  }
  
  //字符串+=运算
  MyString& operator+=(const MyString& other) {
    MyString old = *this;  // 保存已存在的字符串，即：旧字符串
    delete[] str_;   // 清空内存
    size_ = old.size_ + other.size_;
    capacity_ = old.capacity_ + other.capacity_;
    str_ = new char[capacity_]{'\0'};  // 根据两个字符串的空间大小，重新申请一块内存
    strcpy(str_, old.str_); // 将旧字符串复制到申请的内存
    strcat(str_, other.str_); // 将新字符串复制到申请的内存并连接在新字符串的后面
    return *this;
  }

  //字符串下标运算
  char operator[](unsigned int n) {
    return str_[n];
  }

  //友元函数
  //字符串输出
  friend ostream& operator<<(ostream& out, const MyString& string) {
    if (nullptr == &string) { // 非空验证
      return out;
    }
    out << string.str_;
    return out;
  }
  //字符串输入
  friend istream& operator>>(istream& in, MyString& string) {
    if (nullptr == &string) {
      return in;
    }
    memset(string.str_, 0, string.capacity_); // 清空数据
    in >> string.str_;
    return in;
  }
  //字符串+运算
  friend MyString operator+(const MyString& string1, const MyString& string2) {
    MyString string = string1;
    string += string2;
    return string;
  }
  //字符串==运算
  friend bool operator==(const MyString& string1, const MyString& string2) {
    return (bool)(!strcmp(string1.str_, string2.str_));
  }
  //字符串!=运算
  friend bool operator!=(const MyString& string1, const MyString& string2) {
    return (bool)(strcmp(string1.str_, string2.str_));
  }

 private:
  char* str_;
  int size_;
  int capacity_;
};

}


#endif
